/**
 * 通过JSON配置加载多组动画的工具类
 * 
 * @Author 天下无敌
 * @Date 使用JSON配置多组动画
 */
package com.ecs.core.utils;

import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;

public class JsonAnimation {

    // 动画数据：键为动画名称，值为坐标数组
    public ObjectMap<String, FrameCoordinate[]> animationsData = new ObjectMap<>();

    // 动画帧间隔时间：键为动画名称，值为帧间隔时间
    public ObjectMap<String, Float> frameDurations = new ObjectMap<>();

    // 纹理图片路径
    public String texturePath;

    // 单帧的宽度和高度
    public int frameWidth;
    public int frameHeight;

    // 动画播放模式(默认循环)
    private Animation.PlayMode playMode = Animation.PlayMode.LOOP;

    /**
     * 从JSON文件加载动画集
     * @param jsonPath JSON文件路径
     * @param assetManager 资源管理器
     * @return 包含所有动画的映射表
     * @throws GdxRuntimeException 如果JSON文件不存在或格式错误
     * @throws IllegalArgumentException 如果参数无效
     * @throws AnimationConfigurationException 如果动画配置有问题
     */
    public static ObjectMap<String, Animation<TextureRegion>> loadAnimations(
		String jsonPath, 
		AssetManager assetManager) 
	throws GdxRuntimeException, IllegalArgumentException, AnimationConfigurationException {

        // 参数检查
        if (jsonPath == null || jsonPath.isEmpty()) {
            throw new IllegalArgumentException("JSON路径不能为空");
        }

        if (assetManager == null) {
            throw new IllegalArgumentException("AssetManager不能为空");
        }

        // 加载JSON配置
        Json json = new Json();
		//json.setSerializer(JsonAnimation.class,new JsonAnimationSerializer());
        JsonAnimation config;
        try {
            config = json.fromJson(JsonAnimation.class, Gdx.files.internal(jsonPath));
        } catch (GdxRuntimeException e) {
            throw new GdxRuntimeException("加载动画配置文件失败: " + jsonPath, e);
        }

        // 配置验证
        validateConfig(config);

        // 加载纹理
        if (!assetManager.isLoaded(config.texturePath)) {
            throw new AnimationConfigurationException("纹理未加载: " + config.texturePath);
        }

        try {
            Texture texture = assetManager.get(config.texturePath, Texture.class);

            // 切割纹理图集
            TextureRegion[][] textureRegions;
            try {
                textureRegions = TextureRegion.split(
                    texture, 
                    config.frameWidth, 
                    config.frameHeight
                );
            } catch (IllegalArgumentException e) {
                throw new AnimationConfigurationException("纹理切割失败，请检查帧宽高设置", e);
            }

            ObjectMap<String, Animation<TextureRegion>> animations = new ObjectMap<>();

            // 为每个动画创建Animation对象
            for (String animationName : config.animationsData.keys()) {
                FrameCoordinate[] frames = config.animationsData.get(animationName);

                // 检查动画帧数据
                if (frames == null || frames.length == 0) {
                    throw new AnimationConfigurationException("动画'" + animationName + "'没有帧数据");
                }

                Array<TextureRegion> regions = new Array<>(frames.length);

                try {
                    // 获取每一帧的纹理区域
                    for (FrameCoordinate frame : frames) {
                        if (frame.row < 0 || frame.col < 0) {
                            throw new AnimationConfigurationException(
                                "动画'" + animationName + "'包含无效的帧坐标: row=" + frame.row + ", col=" + frame.col);
                        }
                        regions.add(textureRegions[frame.row][frame.col]);
                    }
                } catch (ArrayIndexOutOfBoundsException e) {
                    throw new AnimationConfigurationException(
                        "动画'" + animationName + "'的帧坐标超出纹理图集范围", e);
                }

                Float frameDuration = config.frameDurations.get(animationName);
                if (frameDuration == null || frameDuration <= 0) {
                    throw new AnimationConfigurationException(
                        "动画'" + animationName + "'的帧间隔时间无效: " + frameDuration);
                }

                Animation<TextureRegion> animation = new Animation<>(
                    frameDuration, 
                    regions, 
                    config.playMode
                );

                animations.put(animationName, animation);
            }

            return animations;
        } catch (GdxRuntimeException e) {
            throw new GdxRuntimeException("创建动画失败", e);
        }
    }

    /**
     * 验证动画配置
     */
    private static void validateConfig(JsonAnimation config) throws AnimationConfigurationException {
        if (config.texturePath == null || config.texturePath.isEmpty()) {
            throw new AnimationConfigurationException("纹理路径未配置");
        }

        if (config.frameWidth <= 0 || config.frameHeight <= 0) {
            throw new AnimationConfigurationException(
                "帧宽高必须大于0: width=" + config.frameWidth + ", height=" + config.frameHeight);
        }

        if (config.animationsData == null || config.animationsData.size == 0) {
            throw new AnimationConfigurationException("没有配置动画数据");
        }

        if (config.frameDurations == null || config.frameDurations.size == 0) {
            throw new AnimationConfigurationException("没有配置帧间隔时间");
        }

        // 检查每个动画是否有对应的帧间隔时间
        for (String animationName : config.animationsData.keys()) {
            if (!config.frameDurations.containsKey(animationName)) {
                throw new AnimationConfigurationException(
                    "动画'" + animationName + "'缺少帧间隔时间配置");
            }
        }
    }

    /**
     * 帧坐标内部类
     */
    public static class FrameCoordinate {
        public int row; // 行
        public int col; // 列

        public FrameCoordinate() {}

        public FrameCoordinate(int row, int col) {
            this.row = row;
            this.col = col;
        }
    }
    /**
     * 自定义动画配置异常
     */
    public static class AnimationConfigurationException extends RuntimeException {
		public static final long serialVersionUID = 185246799;
        public AnimationConfigurationException(String message) {
            super(message);
        }

        public AnimationConfigurationException(String message, Throwable cause) {
            super(message, cause);
        }
    }
}
